Conversation
Installer's _daemon_reload went straight to subprocess systemctl, which blows up inside a container with 'System has not been booted with systemd as init system (PID 1)'. The quadlet files had already been written to disk before this point, leaving the operator with a half-applied install and a bug-report traceback. setup.py already had the right pattern — try D-Bus first, fall back to systemctl, warn instead of raise on failure — but installer.py never got updated to use it. Move the helper into psi.systemd as a public daemon_reload() and have both setup.py and installer.py call it. Downgrade CalledProcessError from systemctl to a warning so the install keeps going; the operator can run daemon-reload on the host afterward. The regression test patches subprocess.run to raise CalledProcessError and confirms daemon_reload() returns normally, matching the behavior needed when running inside the psi container.
psi systemd install wrote a quadlet that podman quadlet-generator rejected with: converting "psi-secrets.container": invalid service Type 'simple' The .service unit was never created, so systemctl restart psi-secrets.service failed with 'Unit not found' — a half-applied install with no clear error. Quadlet .container units only allow Type=notify (default), forking, oneshot, or exec. Long-running psi serve works fine under the Type=notify default, which podman wires up via its built-in sdnotify support. Also add ContainerName= to the serve, setup, and tls-renew generators. Without it, quadlet names the container systemd-<unit>, and routine operator commands like podman exec psi-secrets break.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three bugs that together prevent
psi systemd install --mode containerfrom producing a working install when run inside a psi container:_daemon_reloadwent straight tosubprocess.run(["systemctl", "daemon-reload"], check=True), which fails inside a container withSystem has not been booted with systemd as init system (PID 1)and aborts the whole install with a stacktrace after the quadlet files have already been written.Type=simple.generate_container_serve_quadletemittedType=simplein the[Service]section. Podman's quadlet generator rejects this:converting "psi-secrets.container": invalid service Type 'simple'. The resulting.serviceunit is never created, sosystemctl restart psi-secrets.servicefails withUnit not found.ContainerName. WithoutContainerName=, quadlet names the running containersystemd-psi-secrets(etc.). Operator commands likesudo podman exec psi-secrets psi cache statussilently stop working against the regenerated unit.Why
This was discovered while testing PR #16 on the test server. The operator ran the one-shot container invocation to regenerate quadlets, hit the
daemon-reloadcrash, patched around it manually, then hitUnit psi-secrets.service not foundon restart because the emitted quadlet was untranslatable.podman exec psi-secretswould also break even if the quadlet did translate, because the container name would have changed.The symptoms only appeared now because until PR #16 / #17 nobody had actually run
psi systemd install --mode containerin a real deployment — the existing test server uses a Butane-managed hand-crafted quadlet.What changes
psi/systemd.pydaemon_reload(scope)helper that tries D-Bus first, falls back tosystemctl, and downgrades bothFileNotFoundErrorandCalledProcessErrorto warnings._dbus_daemon_reload(scope)as the underlying D-Bus call.psi/installer.py_daemon_reloadnow delegates topsi.systemd.daemon_reload.psi/setup.py_systemd_daemon_reload,_dbus_daemon_reload), importsdaemon_reloadfrompsi.systemd, drops the now-unusedsubprocessimport.psi/unitgen.pygenerate_container_serve_quadlet:Type=simple(quadlet defaultType=notifyworks via podman's sdnotify wiring).ContainerName=psi-secrets.generate_container_provider_setup_quadlet: addsContainerName=psi-<provider>-setup.generate_container_tls_renew_quadlet: addsContainerName=psi-tls-renew.Tests
tests/test_systemd.py: moves the 5 daemon-reload tests fromtest_setup.pyand adds a regression test covering theCalledProcessErrorpath that triggered the container crash.tests/test_setup.py: deletes the moved tests and the stale import.tests/test_unitgen.py: newTestQuadletTranslatabilityclass with 5 tests — noType=simpleunder any cache backend,Type=oneshotpreserved on setup,ContainerNamepresent on all three container quadlets.Test plan
uv run ruff check psi/ tests/— cleanuv run ruff format --check psi/ tests/— cleanuv run ty check— cleanuv run pytest -q— 294 passed (6 new)podman run ... systemd install ...and confirm it exits 0 with only a warning aboutsystemctlsudo systemctl daemon-reloadon the host, thensystemctl restart psi-secrets.service— unit must translate cleanly and the container must come up healthysudo podman exec -i psi-secrets psi cache status— returns in well under a secondsudo podman exec -i psi-secrets psi cache status --verify— flag now recognized; decrypts via HSM